//
//  ZYGCDTimer.m
//  OC_Principle
//
//  Created by wangzhipan on 2025/2/28.
//

#import "ZYGCDTimer.h"

static NSMutableDictionary *_taskDict;
static dispatch_semaphore_t _semaphore;

@implementation ZYGCDTimer

+ (void)initialize
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _semaphore = dispatch_semaphore_create(1);
        _taskDict = [NSMutableDictionary dictionary];
    });
}

+ (nullable ZYTimerTask *)scheduleTimerWithTarget:(id)target
                                         selector:(SEL)sel
                                            delay:(NSTimeInterval)delay
                                         interval:(NSTimeInterval)interval
                                           repeat:(BOOL)repeat
                                     isMainThread:(BOOL)isMainThread
{
    if (interval <= 0 || interval < 0 || repeat <= 0) {
        return nil;
    }
    dispatch_queue_t queue = isMainThread ? dispatch_get_main_queue() : dispatch_get_global_queue(0, 0);
    
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
                                                     0,
                                                     0,
                                                     queue);
    dispatch_source_set_timer(timer,
                              dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC),
                              interval * NSEC_PER_SEC,
                              0);
    
    
    
    
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
    ZYTimerTask *task = [NSString stringWithFormat:@"%p_%d", timer, arc4random() % 1000000];
    NSLog(@"ZYGCDTimer task== %@", task);
    _taskDict[task] = timer;
    dispatch_semaphore_signal(_semaphore);
    
    dispatch_source_set_event_handler(timer, ^{
        if ([target respondsToSelector:sel]) {
            [target performSelector:sel];
        }
        if (!repeat) {
            [self cancelTask:task];
        }
    });
    dispatch_resume(timer);
    return task;
}

+ (void)cancelTask:(ZYTimerTask *)task
{
    if (!task) {
        return;
    }
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
    dispatch_source_t timer = _taskDict[task];
    if (timer) {
        dispatch_source_cancel(timer);
        [_taskDict removeObjectForKey:task];
    }
    dispatch_semaphore_signal(_semaphore);
}

@end
